
#include "./fiber-env.h"

#include "./cooperative-condition.h"
#include "./cooperative-event.h"
#include "./cooperative-file.h"
#include "./cooperative-mutex.h"
#include "./cooperative-rwlock.h"
#include "./cooperative-semaphore.h"
#include "./cooperative-socket.h"
#include "./fiber-env-impl.h"

namespace fasmio { namespace fiber_env {

FiberEnv* NewFiberEnv()
{
    return new FiberEnvImpl();
}

/////////////////////////////////////////////////////////////////////////////

ITCPSocket* NewTCPSocket()
{
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeTCPSocket();
}

IFile* NewFile()
{
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeFile();
}

IMutex* NewMutex(bool recursive)
{
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeMutex(recursive);
}

IRWLock* NewRWLock()
{
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeRWLock();
}

ICondition* NewCondition(IMutex *mutex)
{
    if (mutex == nullptr)
        return nullptr;
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    CooperativeMutex *cooperative_mutex = dynamic_cast<CooperativeMutex*>(mutex);
    if (cooperative_mutex == nullptr)
        return nullptr;

    return new CooperativeCondition(cooperative_mutex);
}

IEvent* NewEvent(bool init_state)
{
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeEvent(init_state);
}

ISemaphore* NewSemaphore(unsigned int max_count, unsigned int init_count)
{
    if (max_count == 0)
        return nullptr;
    if (max_count < init_count)
        return nullptr;
    if (FiberEnvImpl::GetThreadContext() == nullptr)
        return nullptr;

    return new CooperativeSemaphore(max_count, init_count);
}

/////////////////////////////////////////////////////////////////////////////

void Sleep(unsigned long milliseconds)
{
    FiberEnvImpl::Sleep(milliseconds);
}

void Yield()
{
    FiberEnvImpl::Yield();
}

void Quit(int quit_code)
{
    FiberEnvImpl::Quit(quit_code);
}

void NotifyToStop()
{
    FiberEnvImpl::NotifyToStop_s();
}

Fiber* CreateFiber(int (*func)(void*), void* arg, const char* name)
{
    return FiberEnvImpl::CreateFiber_s(func, arg, name);
}

Fiber* SelfFiber()
{
    return FiberEnvImpl::SelfFiber();
}

void DumpFibers(FILE* fp)
{
    if (fp != nullptr)
        FiberEnvImpl::DumpFibers_s(fp);
}

}}  // namespace fasmio::fiber_env

